﻿#include "ManectricClaw.h"
#include "../../../Shared/Functions/Functions.h"
#include "../../MirEnvir/Envir.h"
#include "../../../Shared/ServerPackets.h"
#include "../DelayedAction.h"
#include "../../../Shared/Enums.h"
#include "../../MirEnvir/Map.h"
#include "../../../Shared/Data/Stat.h"
#include "../MapObject.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
namespace S = ServerPackets;

namespace Server::MirObjects::Monsters
{

    ManectricClaw::ManectricClaw(MonsterInfo *info) : MonsterObject(info)
    {
    }

    bool ManectricClaw::InAttackRange()
    {
        return getCurrentMap() == getTarget()->getCurrentMap() && Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), AttackRange);
    }

    void ManectricClaw::Attack()
    {
        if (!getTarget()->IsAttackTarget(this))
        {
            setTarget(nullptr);
            return;
        }

        ShockTime = 0;

        setDirection(Functions::DirectionFromPoint(getCurrentLocation(), getTarget()->getCurrentLocation()));
        bool ranged = getCurrentLocation() == getTarget()->getCurrentLocation() || !Functions::InRange(getCurrentLocation(), getTarget()->getCurrentLocation(), 1);

        if (ranged || getEnvir()->getTime() > _thrustTime)
        {
            if (ranged && getEnvir()->Random->Next(2) == 0)
            {
                MoveTo(getTarget()->getCurrentLocation());
                ActionTime = getEnvir()->getTime() + 300;
                return;
            }

            S::ObjectRangeAttack *tempVar = new S::ObjectRangeAttack();
            tempVar->ObjectID = ObjectID;
            tempVar->Direction = getDirection();
            tempVar->Location = getCurrentLocation();
            tempVar->TargetID = getTarget()->ObjectID;
            Broadcast(tempVar);

            AttackTime = getEnvir()->getTime() + AttackSpeed;

            DelayedAction *action = new DelayedAction(DelayedType::RangeDamage, getEnvir()->getTime() + 500);
            ActionList.push_back(action);

            _thrustTime = getEnvir()->getTime() + 5000;

//C# TO C++ CONVERTER TODO TASK: A 'delete action' statement was not added since action was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        MonsterObject::Attack();
    }

    void ManectricClaw::CompleteRangeAttack(std::vector<std::any> &data)
    {
        IceThrust();
    }

    void ManectricClaw::IceThrust()
    {
        Point *location = getCurrentLocation();
        MirDirection direction = getDirection();
        Cell *cell;

        int nearDamage = GetAttackPower(Stats[Stat::MinDC], Stats[Stat::MaxDC]);
        int farDamage = GetAttackPower(Stats[Stat::MinMC], Stats[Stat::MaxMC]);

        int col = 3;
        int row = 3;

        std::vector<Point*> loc(col); //0 = left 1 = center 2 = right
        loc[0] = Functions::PointMove(location, Functions::PreviousDir(direction), 1);
        loc[1] = Functions::PointMove(location, direction, 1);
        loc[2] = Functions::PointMove(location, Functions::NextDir(direction), 1);

        for (int i = 0; i < col; i++)
        {
            Point *startPoint = loc[i];
            for (int j = 0; j < row; j++)
            {
                Point *hitPoint = Functions::PointMove(startPoint, direction, j);

                if (!getCurrentMap()->ValidPoint(hitPoint))
                {
                    continue;
                }

                cell = getCurrentMap()->GetCell(hitPoint);

                if (cell->Objects.empty())
                {
                    continue;
                }

                for (int k = 0; k < cell->Objects.size(); k++)
                {
                    MapObject *target = cell->Objects[k];
                    switch (target->getRace())
                    {
                        case ObjectType::Monster:
                        case ObjectType::Player:
                            if (target->IsAttackTarget(this))
                            {
                                if (target->Attacked(this, j <= 1 ? nearDamage : farDamage, DefenceType::MAC) > 0)
                                {
                                    PoisonTarget(target, 5, target->getRace() == ObjectType::Player ? 4 : 5 + getEnvir()->Random->Next(5), PoisonType::Slow, 1000);
                                    PoisonTarget(target, 5, target->getRace() == ObjectType::Player ? 2 : 5 + getEnvir()->Random->Next(this->Stats[Stat::Freezing]), PoisonType::Frozen, 1000);
                                }
                            }
                            break;
                    }
                }
            }
        }
    }
}
